package com.scalar.chiptrack.operations.process;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.StringTokenizer;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.scalar.chiptrack.adaptor.Adaptor;
import com.scalar.chiptrack.adaptor.AdaptorList;
import com.scalar.chiptrack.adaptor.AdaptorXmlHandler;
import com.scalar.chiptrack.jobs.JobHandler;
import com.scalar.chiptrack.jobs.dao.JobDAO;
import com.scalar.chiptrack.utils.ConfigManager;


public class RunAdaptorCommunicator extends HttpServlet
 {

    public void doGet( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
    {

        ObjectInputStream inputFromApplet = null;
        ObjectOutputStream outputToApplet = null;
        PrintStream console = System.out;
        PrintStream out = null;
        String vendorNames = null;
        String vendorName = null;
        String RES_COMPLETE = "complete";
        boolean success = true;

        inputFromApplet = new ObjectInputStream( request.getInputStream() );

        try
        {

            //Getting On Demand Adaptor Status from DB.
            boolean onDemandAdaptorStatus = JobDAO.getOnDemandAdaptorStatus();

            if ( onDemandAdaptorStatus == true )
            {
                //step1: Getting the ondemandadaptor timeout
                int timeOut = 0;
                try
                {
                    timeOut = Integer.parseInt ( ConfigManager.getOnDemandAdaptorStatusTimeOut() );
                }
                catch( NumberFormatException ignore ){}

                //step2: update the statusto false( ie not running status ) if timeOut minutes elapsed
                JobDAO.updateOnDemandAdaptorStatusOnTimeOut( null, Boolean.FALSE.booleanValue(), timeOut );

                //Getting On Demand Adaptor Status from DB.
                onDemandAdaptorStatus = JobDAO.getOnDemandAdaptorStatus();

            }

            // If It's not in Running Status(means 1 Value in DB), Starting The Scheduler.
            if ( onDemandAdaptorStatus == false )
            {
                try
                {
                    JobDAO.updateOnDemandAdaptorStatus( Boolean.TRUE );
                    vendorNames = (String)inputFromApplet.readObject();
                    //System.out.println( "Vendor Names = "+vendorNames );

                    LinkedHashMap map = getAdaptorsMap();

                    StringTokenizer st = new StringTokenizer( vendorNames , "," );

                    while ( st.hasMoreTokens() )
                    {
                        vendorName = st.nextToken();
                        success = true;

                        if( vendorName !=  null )
                        {
                            Adaptor adaptor = (Adaptor)map.get( vendorName );
                            ArrayList list = adaptor.getAdaptorList();
                            Iterator it = list.iterator();
                            //outputToApplet = new ObjectOutputStream( response.getOutputStream() );
                            out = new PrintStream( response.getOutputStream(), true );
                            System.setOut( out );

                            while( it.hasNext() )
                            {
                                AdaptorList alist = (AdaptorList)it.next();
                                //System.out.println(alist);
                                System.out.println( "Executing ...." + alist.getAdaptorClassName() );
                                if( null != alist.getAdaptorClassName() )
                                {
                                    try
                                    {
                                        dynamicClassLoader( alist.getAdaptorClassName() );
                                    }
                                    catch(Exception e)
                                    {
                                        success = false;
                                        e.printStackTrace();
                                    }
                                    if ( success == false )
                                    {
                                       System.out.println( "\n<li>"+vendorName + " Adaptor Failed." );
                                    }
                                }

                                //when adaptor Runs successfully, Parser executes
                                if ( success == true )
                                {
                                    System.out.println( "Executing ...."+alist.getParserClassName() );
                                    if( null != alist.getParserClassName()  )
                                    {
                                        try
                                        {
                                            dynamicClassLoader( alist.getParserClassName() );
                                        }
                                        catch(Exception e)
                                        {
                                            success = false;
                                            e.printStackTrace();
                                        }
                                        if ( success == false )
                                        {
                                            System.out.println("\n<li>"+ vendorName + " Parser Failed." );
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
                catch ( Exception e ){}

                //Updating the On Demand Adaptor Stauts to 1. i.e updating Status to Stopped.
                try
                {
                    JobDAO.updateOnDemandAdaptorStatus( Boolean.FALSE );
                } catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
            else
            {
                out = new PrintStream( response.getOutputStream(), true );
                System.setOut( out );
                System.out.println("\n<li> Adaptors already Running. Please try after some time.");
            }
            //int i = 0;

            //outputToApplet = new ObjectOutputStream( response.getOutputStream() );

            /*while(i<=10){
                   System.out.println("I = "+i);
                   outputToApplet.writeObject(vendorName+i);
                   outputToApplet.flush();
                   Thread.sleep(500);
                   i++;
               }*/

            //outputToApplet.writeObject(RES_COMPLETE);
            //outputToApplet.flush();
            //outputToApplet.close();
            //System.out.println(RES_COMPLETE);

        }
        catch(Exception e)
        {
            //e.printStackTrace();
        }
        finally
        {
           //if ( success == true )
           //{
                if( null != out )
                {
                    out.close();
                }

                if( null != inputFromApplet )
                {
                    inputFromApplet.close();
                }

                System.setOut( console );
           //}
        }
    }
    public void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException, IOException
    {
        doGet( request, response );
    }

    public LinkedHashMap getAdaptorsMap()
    {

        LinkedHashMap map = null;

        try
        {

            AdaptorXmlHandler handler = new AdaptorXmlHandler();
            map = handler.getAdaptorList();
            /*Iterator it = map.keySet().iterator();
               while(it.hasNext()){
                   String key = (String)it.next();
                   //System.out.println("Key = "+key);
                   Adaptor adaptor = (Adaptor)map.get(key);
                   ArrayList list = adaptor.getAdaptorList();

                   Iterator its = list.iterator();
                   while(its.hasNext()){
                       System.out.println(its.next());
                   }
               }*/

        }
        catch(Exception e)
        {
            e.printStackTrace();
        }

        return map;
    }

    public void dynamicClassLoader( String className ) throws Exception
    {
        JobHandler handler = (JobHandler) Class.forName( className ).newInstance();
        handler.execute();
        //Class toRun = Class.forName( className );
        //Method executeMethod = findExecuteMethod( toRun );
        //executeMethod.invoke( toRun.newInstance(), null );
    }

    public Method findExecuteMethod( Class toRun )
    {

        Method[] methods = toRun.getMethods();

        for( int i=0; i<methods.length; i++ )
        {
            if( "execute".equalsIgnoreCase( methods[i].getName() ) )
            {
                return methods[i];
            }
        }

        return null;
    }
}